﻿using Mate.Core.Base;
using Mate.Core.Configuration;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Qiniu.Storage;
using Qiniu.Util;
using System;
using System.Collections.Generic;
using System.DrawingCore;
using System.DrawingCore.Drawing2D;
using System.DrawingCore.Imaging;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace Mate.Framework.Extensions
{
    public static class UploadExtensions
    {
        private static readonly string _PicturePath = "/Images/";
        private static readonly string _FilePath = "/File/";

        /// <summary>
        /// 生成图片宽度
        /// </summary>
        private const int _DEFAULTWIDTH = 200;
        /// <summary>
        /// 生成图片高度
        /// </summary>
        private const int _DEFAULTHEIGHT = 200;

        #region 上传图片
        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="file">HttpPostedFileBase对象</param>
        /// <param name="picturePath">图片目录</param>
        /// <returns></returns>
        public static BaseResult Picture(this IFormFile file, string webRoot, string picturePath)
        {
            string zoomPath;
            return Picture(file, webRoot, picturePath, false, _DEFAULTWIDTH, _DEFAULTHEIGHT, out zoomPath);
        }

        /// <summary>
        /// 上传图片并生成缩略图
        /// </summary>
        /// <param name="file">HttpPostedFileBase对象</param>
        /// <param name="picturePath">图片目录</param>
        /// <param name="zoomWidth">生成图片宽度</param>
        /// <param name="zoomHeight">生成图片高度</param>
        /// <param name="zoomPath">out 生成缩略图的路径</param>
        /// <returns></returns>
        public static BaseResult Picture(this IFormFile file, string webRoot, string picturePath, out string zoomPath, int zoomWidth = _DEFAULTWIDTH, int zoomHeight = _DEFAULTHEIGHT)
        {
            return Picture(file, webRoot, picturePath, true, zoomWidth, zoomHeight, out zoomPath);
        }

        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="file">HttpPostedFileBase对象</param>
        /// <param name="picturePath">图片目录</param>
        /// <param name="zoom">是否生成缩图</param>
        /// <param name="zoomWidth">如果生成缩略图，生成图片宽度</param>
        /// <param name="zoomHeight">如果生成缩略图，生成图片高度</param>
        /// <returns></returns>
        private static BaseResult Picture(this IFormFile file, string webRoot, string picturePath, bool zoom, int zoomWidth, int zoomHeight, out string zoomPath)
        {
            var result = new BaseResult();
            zoomPath = "";
            if (file == null || file.Length == 0)
            {
                result.ResultCode = ResultCode.Fail;
                result.Message = "请选择图片！";
                return result;
            }
            if (!string.IsNullOrWhiteSpace(picturePath))
            {
                picturePath += "/";
            }
            string newname = Guid.NewGuid().ToString();
            string suffix = Path.GetExtension(file.FileName);

            //检查文件扩展名是否合法
            if (!CheckImageExt(suffix))
            {
                result.ResultCode = ResultCode.Fail;
                result.Message = "不允许上传" + suffix + "类型的文件，请重新选择！";
                return result;
            }
            //检查文件大小是否合法
            if (!CheckImageSize(file.Length))
            {
                result.ResultCode = ResultCode.Fail;
                result.Message = "文件超过限制的大小！";
                return result;
            }

            CreateDirectory(webRoot + _PicturePath + picturePath);
            try
            {
                //上传原图
                using (FileStream fs = File.Create(webRoot + _PicturePath + picturePath + newname + suffix))
                {
                    file.CopyTo(fs);
                    fs.Flush();
                }


                //生成缩略图
                //if (zoom)
                //{
                //    var zoomResult = PictureZoom(file, picturePath, newname, suffix, zoomWidth, zoomHeight);
                //    if (zoomResult.IsSuccess) zoomPath = zoomResult.Data as string;
                //}
                result.ResultCode = ResultCode.Success;
                result.Message = "上传成功";
                result.Data = _PicturePath + picturePath + newname + suffix;
            }
            catch (Exception ex)
            {
                result.ResultCode = ResultCode.Fail;
                result.Message = "上传图片失败！" + ex.Message;
            }
            return result;
        }
        #endregion


        #region 上传图片并生成缩略图
        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="file">HttpPostedFileBase对象</param>
        /// <param name="picturePath">生成图片存放目录</param>
        /// <param name="filename">图片名称</param>
        /// <param name="suffix">图片后缀</param>
        /// <param name="width">生成图片宽度</param>
        /// <param name="height">生成图片高度</param>
        /// <returns></returns>
        private static BaseResult PictureZoom(this IFormFile file, string webRoot, string picturePath, string filename, string suffix, int width, int height)
        {
            var result = new BaseResult();
            //从文件获取图片对象
            Image image = Image.FromStream(file.OpenReadStream(), true);
            double newWidth, newHeight;

            filename = GetSizeFileName(filename, width, height);
            if (image.Width > width || image.Height > height)
            {
                if (image.Width >= image.Height)
                {
                    newWidth = width;
                    newHeight = image.Height * (newWidth / image.Width);
                }
                else
                {
                    newHeight = height;
                    newWidth = image.Width * (newHeight / image.Height);
                }
            }
            else
            {
                newWidth = image.Width;
                newHeight = image.Height;
            }


            Size size = new Size((int)newWidth, (int)newHeight); //设置图片的宽度和高度
            Image bitmap = new Bitmap(size.Width, size.Height);  //新建bmp图片
            Graphics g = Graphics.FromImage(bitmap);  //新建画板
            g.InterpolationMode = InterpolationMode.High;  //制定高质量插值法
            g.SmoothingMode = SmoothingMode.HighQuality;   //设置高质量、低速度呈现平滑程度
            g.Clear(Color.White);    //清空画布
            //在制定位置画图
            g.DrawImage(image, new Rectangle(0, 0, bitmap.Width, bitmap.Height), new Rectangle(0, 0, image.Width, image.Height), GraphicsUnit.Pixel);

            string path = _PicturePath + picturePath + filename + suffix;
            try
            {
                using (FileStream fs = File.Create(webRoot + path))
                {
                    file.CopyTo(fs);
                    fs.Flush();
                }
                result.ResultCode = ResultCode.Success;
                result.Data = path;
            }
            catch (Exception ex)
            {
                result.ResultCode = ResultCode.Fail;
                result.Message = "生成缩略图失败！" + ex.Message;
            }
            finally
            {
                g.Dispose();
                bitmap.Dispose();
                image.Dispose();
            }
            return result;
        }

        /// <summary>
        /// 获取要生成图片类型
        /// </summary>
        /// <param name="suffix">图片后缀</param>
        /// <returns></returns>
        private static ImageFormat GetImageFormat(string suffix)
        {
            suffix = suffix.ToLower();
            if (suffix == ".gif")
            {
                return ImageFormat.Gif;
            }
            else if (suffix == ".png")
            {
                return ImageFormat.Png;
            }
            else
            {
                return ImageFormat.Jpeg;
            }
        }

        /// <summary>
        /// 根据图片类型获取图片上传的目录
        /// </summary>
        /// <param name="pictureType">图片类型</param>
        /// <returns></returns>
        private static string CreateDirectory(string path)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            return path;
        }

        /// <summary>
        /// 返回缩略图名称
        /// </summary>
        /// <param name="filename">图片名称</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <returns></returns>
        private static string GetSizeFileName(string filename, int width, int height)
        {
            if (width > 0 && height > 0)
            {
                return filename + "_" + width + "" + height;
            }
            else
            {
                return filename;
            }
        }

        /// <summary>
        /// 检查是否为合法的上传文件
        /// </summary>
        private static bool CheckImageExt(string _fileExt)
        {
            //检查危险文件
            string[] excExt = { ".jpg", ".jpeg", ".gif", ".png" };
            for (int i = 0; i < excExt.Length; i++)
            {
                if (excExt[i].ToLower() == _fileExt.ToLower())
                {
                    return true;
                }
            }
            return false;
        }

        private static bool CheckImageSize(long _fileSize)
        {
            if (_fileSize > 1024 * 1024 * 10)
            {
                return true;
            }
            return true;
        }

        #endregion

        #region 上传文件
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="file"></param>
        /// <param name="filePath">文件目录</param>
        /// <returns></returns>
        //public static BaseResult UploadFile(this HttpPostedFileBase file, string filePath)
        //{
        //    if (file == null || file.ContentLength == 0) return new BaseResult(false, "", "请选择文件！");
        //    if (!string.IsNullOrWhiteSpace(filePath))
        //    {
        //        filePath += "/";
        //    }
        //    else
        //    {
        //        filePath = DateTime.Now.ToString("yyyyMM");
        //    }
        //    string newname = Guid.NewGuid().ToString();
        //    string suffix = Path.GetExtension(file.FileName);

        //    string[] fileSuffix = System.Configuration.ConfigurationManager.AppSettings["fileSuffix"].ToString().Split(',');
        //    if (!fileSuffix.Contains(suffix))
        //    {
        //        return new BaseResult(false, "", "选择文件后缀有误，不支持上传该文件！");
        //    }

        //    string path = filePath + newname + suffix;
        //    CreateDirectory(_UploadFilePath + filePath);
        //    try
        //    {
        //        //上传文件
        //        file.SaveAs(_UploadFilePath + path);
        //        return new BaseResult(true, _FilePath + path);
        //    }
        //    catch (Exception ex)
        //    {
        //        return new BaseResult(false, "", "上传文件失败！" + ex.Message);
        //    }
        //}
        #endregion

        #region 七牛图片上传
        private static BaseResult QiniuStream(Stream stream, QiniuConfig qiniu, string suffix)
        {

            BaseResult result = new BaseResult();

            try
            {

                var generateFileName = $"{DateTime.Now.ToString("yyyyMMddHHmmssfff-")}{Guid.NewGuid().GetHashCode().ToString().Replace("-", string.Empty)}{suffix}";
                var saveKey = $"wl/maple/{generateFileName}";

                // 生成(上传)凭证时需要使用此Mac
                // 这个示例单独使用了一个Settings类，其中包含AccessKey和SecretKey
                // 实际应用中，请自行设置您的AccessKey和SecretKey
                Mac mac = new Mac(qiniu.AccessKey, qiniu.SecretKey);
                // 上传策略，参见 
                // https://developer.qiniu.com/kodo/manual/put-policy
                PutPolicy putPolicy = new PutPolicy();
                // 如果需要设置为"覆盖"上传(如果云端已有同名文件则覆盖)，请使用 SCOPE = "BUCKET:KEY"
                // putPolicy.Scope = bucket + ":" + saveKey;
                putPolicy.Scope = qiniu.Bucket;
                // 上传策略有效期(对应于生成的凭证的有效期)   
                putPolicy.SetExpires(3600);
                // 上传到云端多少天后自动删除该文件，如果不设置（即保持默认默认）则不删除
                //putPolicy.DeleteAfterDays = 1;

                // 生成上传凭证，参见
                // https://developer.qiniu.com/kodo/manual/upload-token            
                string jstr = putPolicy.ToJsonString();
                string token = Auth.CreateUploadToken(mac, jstr);
                Config config = new Config();
                // 设置上传区域
                config.Zone = Zone.ZONE_CN_East;
                // 设置 http 或者 https 上传
                config.UseHttps = true;
                config.UseCdnDomains = true;
                config.ChunkSize = ChunkUnit.U512K;
                FormUploader fu = new FormUploader(config);
                var uploadResult = fu.UploadStream(stream, saveKey, token, null);
                if (uploadResult.Code == 200)
                {
                    result.Message = "上传成功";
                    result.ResultCode = ResultCode.Success;
                    result.Data = qiniu.ImgUrl + saveKey;
                    return result;
                }
                result.Message = "上传失败";
                result.ResultCode = ResultCode.Fail;
                result.Data = saveKey;
            }
            catch (Exception ex)
            {
                result.Message = "上传失败：{ex.Message}";
                result.ResultCode = ResultCode.Fail;
            }
            return result;
        }
        /// <summary>
        /// 七牛图片上传
        /// </summary>
        /// <param name="file"></param>
        /// <param name="qiniu"></param>
        /// <returns></returns>
        public static BaseResult QiniuUpload(this QiniuConfig qiniu,IFormFile file)
        {
            BaseResult result = new BaseResult();
            if (file == null || file.Length == 0)
            {
                result.ResultCode = ResultCode.Fail;
                result.Message = "请选择图片！";
                return result;
            }
            string suffix = Path.GetExtension(file.FileName);
            //检查文件扩展名是否合法
            if (!CheckImageExt(suffix))
            {
                result.ResultCode = ResultCode.Fail;
                result.Message = "不允许上传" + suffix + "类型的文件，请重新选择！";
                return result;
            }
            //检查文件大小是否合法
            if (!CheckImageSize(file.Length))
            {
                result.ResultCode = ResultCode.Fail;
                result.Message = "文件超过限制的大小！";
                return result;
            }
            return QiniuStream(file.OpenReadStream(), qiniu,suffix);
        }
        /// <summary>
        /// 七牛图片上传--base64
        /// </summary>
        /// <param name="imgBase64"></param>
        /// <param name="fileName"></param>
        /// <param name="qiniu"></param>
        /// <returns></returns>
        public static BaseResult QiniuUpload(this QiniuConfig qiniu,string imgBase64,string fileName)
        {
            BaseResult result = new BaseResult();
            if (string.IsNullOrWhiteSpace(imgBase64) || string.IsNullOrWhiteSpace(fileName))
            {
                result.ResultCode = ResultCode.Fail;
                result.Message = "请选择图片！";
                return result;
            }
            string suffix = Path.GetExtension(fileName);
            //检查文件扩展名是否合法
            if (!CheckImageExt(suffix))
            {
                result.ResultCode = ResultCode.Fail;
                result.Message = "不允许上传" + suffix + "类型的文件，请重新选择！";
                return result;
            }

            var reg = new Regex("data:image/(.*);base64,");
            imgBase64 = reg.Replace(imgBase64, "");
            byte[] imageByte = Convert.FromBase64String(imgBase64);
            //检查文件大小是否合法
            if (!CheckImageSize(imageByte.Length))
            {
                result.ResultCode = ResultCode.Fail;
                result.Message = "文件超过限制的大小！";
                return result;
            }

            var stream = new MemoryStream(imageByte);
            return QiniuStream(stream, qiniu, suffix);
        }
        #endregion

    }
}
